package com.ecoolex.hotel.saas.core.manager;

import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.hotel.saas.core.dao.SalesUserWalletDAO;
import com.ecoolex.hotel.saas.entity.PresaleCouponOrder;
import com.ecoolex.hotel.saas.entity.PresaleCouponOrderDetail;
import com.ecoolex.hotel.saas.entity.SalesUserWallet;
import com.ecoolex.hotel.saas.entity.SalesUserWallet.Column;
import com.ecoolex.hotel.saas.enums.PresaleCouponDistributionSettleType;
import com.ecoolex.hotel.saas.enums.PresaleCouponOrderStatus;
import com.ecoolex.hotel.saas.enums.SalesUserWalletDetailSource;
import com.ecoolex.hotel.saas.enums.SalesUserWalletDetailType;
import com.ecoolex.hotel.saas.entity.SalesUserWalletExample;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SalesUserWalletManager {
	
    @Autowired
    private SalesUserWalletDAO dao;
    
    @Autowired
    private SalesUserWalletDetailManager walletDetailManager;
    
    @Autowired
    private PresaleCouponOrderDetailManager orderDetailManager;
    
    public void create(Integer storeId, Integer userId, String createUser) {
    	if(Check.notNull(getByUserIdAndStoreId(userId,storeId))) {
    		return;
    	}
    	SalesUserWallet wallet = new SalesUserWallet();
    	wallet.setStoreId(storeId);
    	wallet.setUserId(userId);
    	wallet.setTotalSalesAmt(BigDecimal.ZERO);
    	wallet.setCashOutAmt(BigDecimal.ZERO);
    	wallet.setBalanceAmt(BigDecimal.ZERO);
    	wallet.setWaitInAccountAmt(BigDecimal.ZERO);
    	wallet.setCashOutFrozenAmt(BigDecimal.ZERO);
    	wallet.setDeleted(SalesUserWallet.NOT_DELETED);
    	wallet.setCreateUser(createUser);
    	wallet.setCreateTime(Date.from(Instant.now()));
    	wallet.setUpdateUser(createUser);
    	wallet.setUpdateTime(Date.from(Instant.now()));
    	dao.insert(wallet);
    }
    
    /**
     * 发放佣金到待入账金额
     * @param order
     * @param updateUser
     */
    public void grantCommissionIng(PresaleCouponOrder order, String updateUser) {
    	SalesUserWallet wallet = getByUserIdAndStoreId(order.getSalesUserId(),order.getStoreId());
    	wallet.setTotalSalesAmt(wallet.getTotalSalesAmt().add(order.getTotalPrice()));
    	wallet.setWaitInAccountAmt(wallet.getWaitInAccountAmt().add(order.getCommission()));
    	wallet.setUpdateUser(updateUser);
    	wallet.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(wallet, 
    		Column.totalSalesAmt,
    		Column.waitInAccountAmt,
    		Column.updateUser,
    		Column.updateTime);
    }
    
    /**
     * 待入账转入余额
     * @param order
     * @param updateUser
     */
    public void waitInToBalance(PresaleCouponOrder order, String updateUser) {
    	SalesUserWallet wallet = getByUserIdAndStoreId(order.getSalesUserId(),order.getStoreId());
    	if(Check.notNull(wallet)) {
    		wallet.setBalanceAmt(wallet.getBalanceAmt().add(order.getCommission()));
        	wallet.setWaitInAccountAmt(wallet.getWaitInAccountAmt().subtract(order.getCommission()));
        	wallet.setUpdateUser(updateUser);
        	wallet.setUpdateTime(Date.from(Instant.now()));
        	dao.updateByPrimaryKeySelective(wallet, 
        		Column.waitInAccountAmt,
        		Column.balanceAmt,
        		Column.updateUser,
        		Column.updateTime);
        	//钱包明细
        	walletDetailManager.create(wallet.getWalletId(), 
        		SalesUserWalletDetailType.IN_ACCOUNT.real(),
        		order.getCommission(),
        		SalesUserWalletDetailSource.SALES.real(),
        		order.getOrderId(),
        		null, 
        		updateUser);
    	}
    }
    
    /**
     * 发放佣金到余额
     * @param order
     * @param updateUser
     */
    public void grantCommissionEd(PresaleCouponOrder order, String updateUser) {
    	SalesUserWallet wallet = getByUserIdAndStoreId(order.getSalesUserId(),order.getStoreId());
    	if(Check.notNull(wallet)) {
    		wallet.setTotalSalesAmt(wallet.getTotalSalesAmt().add(order.getTotalPrice()));
        	wallet.setBalanceAmt(wallet.getBalanceAmt().add(order.getCommission()));
        	wallet.setUpdateUser(updateUser);
        	wallet.setUpdateTime(Date.from(Instant.now()));
        	dao.updateByPrimaryKeySelective(wallet, 
        		Column.totalSalesAmt,
        		Column.balanceAmt,
        		Column.updateUser,
        		Column.updateTime);
        	//钱包明细
        	walletDetailManager.create(wallet.getWalletId(), 
        		SalesUserWalletDetailType.IN_ACCOUNT.real(),
        		order.getCommission(),
        		SalesUserWalletDetailSource.SALES.real(),
        		order.getOrderId(),
        		null, 
        		updateUser);
    	}
    }
    
    /**
     * 提现冻结金额
     * @param walletId
     * @param applyAmt
     * @param updateUser
     */
    public void balanceToFrozen(Integer walletId, BigDecimal applyAmt, String updateUser) {
    	SalesUserWallet wallet = get(walletId);
    	wallet.setBalanceAmt(wallet.getBalanceAmt().subtract(applyAmt));
    	wallet.setCashOutFrozenAmt(wallet.getCashOutFrozenAmt().add(applyAmt));
    	wallet.setUpdateUser(updateUser);
    	wallet.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(wallet, 
    		Column.cashOutFrozenAmt,
    		Column.balanceAmt,
    		Column.updateUser,
    		Column.updateTime);
    }
    
    /**
     * 后台同意提现申请，提现到账，扣除冻结金额
     * @param frozenAmt
     * @param updateUser
     */
    public void reduceFrozenAmt(SalesUserWallet wallet, Integer applyId, BigDecimal frozenAmt, String updateUser) {
    	BizAssert.isTrue(Check.isGreatThanEqual(wallet.getBalanceAmt(), BigDecimal.ZERO),
    		ResultCode.BIZ.build(20), 
    		"余额不足");
    	wallet.setCashOutFrozenAmt(wallet.getCashOutFrozenAmt().subtract(frozenAmt));
    	wallet.setCashOutAmt(wallet.getCashOutAmt().add(frozenAmt));
    	wallet.setUpdateUser(updateUser);
    	wallet.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(wallet, 
    		Column.cashOutFrozenAmt,
    		Column.cashOutAmt,
    		Column.updateUser,
    		Column.updateTime);
    	//钱包明细
    	walletDetailManager.create(wallet.getWalletId(), 
    		SalesUserWalletDetailType.OUT_ACCOUNT.real(),
    		frozenAmt,
    		SalesUserWalletDetailSource.CASH_OUT.real(),
    		applyId,
    		null, 
    		updateUser);
    }
    
    /**
     * 后台拒绝提现申请，冻结金额返回余额
     * @param walletId
     * @param frozenAmt
     * @param updateUser
     */
    public void frozenAmtToBalance(Integer walletId, BigDecimal frozenAmt, String updateUser) {
    	SalesUserWallet wallet = get(walletId);
    	wallet.setCashOutFrozenAmt(wallet.getCashOutFrozenAmt().subtract(frozenAmt));
    	wallet.setBalanceAmt(wallet.getBalanceAmt().add(frozenAmt));
    	wallet.setUpdateUser(updateUser);
    	wallet.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(wallet, 
    		Column.cashOutFrozenAmt,
    		Column.balanceAmt,
    		Column.updateUser,
    		Column.updateTime);
    }
    
    /**
     * 强制退款，退款，撤销核销等情况下进行佣金扣除
     * @param order
     * @param updateUser
     */
    public void reduceWaitInOrBalance(PresaleCouponOrder order, String updateUser) {
    	SalesUserWallet wallet = getByUserIdAndStoreId(order.getSalesUserId(),order.getStoreId());
    	List<PresaleCouponOrderDetail> list = orderDetailManager.queryByOrderId(order.getOrderId());
    	Integer settleType = list.get(0).getDistributionSettleType();
    	if(PresaleCouponDistributionSettleType.AFTER_PAY.equal(settleType)) {
    		//支付后结算
    		//扣余额
        	if(Check.notNull(wallet)) {
            	wallet.setBalanceAmt(wallet.getBalanceAmt().subtract(order.getCommission()));
            	wallet.setUpdateUser(updateUser);
            	wallet.setUpdateTime(Date.from(Instant.now()));
            	dao.updateByPrimaryKeySelective(wallet, 
            		Column.balanceAmt,
            		Column.updateUser,
            		Column.updateTime);
            	//钱包明细
            	walletDetailManager.create(wallet.getWalletId(), 
            		SalesUserWalletDetailType.OUT_ACCOUNT.real(),
            		order.getCommission(),
            		SalesUserWalletDetailSource.SALES.real(),
            		order.getOrderId(),
            		null, 
            		updateUser);
        	}
    	}else if(PresaleCouponDistributionSettleType.OTHER.equal(settleType)) {
    		//支付后发放，使用后结算
    		if(PresaleCouponOrderStatus.WAIT_USE.equal(order.getStatus())) {
    			//还未使用，扣待入账金额
    	    	if(Check.notNull(wallet)) {
    	        	wallet.setWaitInAccountAmt(wallet.getWaitInAccountAmt().subtract(order.getCommission()));
    	        	wallet.setUpdateUser(updateUser);
    	        	wallet.setUpdateTime(Date.from(Instant.now()));
    	        	dao.updateByPrimaryKeySelective(wallet, 
    	        		Column.waitInAccountAmt,
    	        		Column.updateUser,
    	        		Column.updateTime);
    	    	}
    		}else if(PresaleCouponOrderStatus.USED.equal(order.getStatus())) {
    			//已使用，扣余额
    			if(Check.notNull(wallet)) {
                	wallet.setBalanceAmt(wallet.getBalanceAmt().subtract(order.getCommission()));
                	wallet.setUpdateUser(updateUser);
                	wallet.setUpdateTime(Date.from(Instant.now()));
                	dao.updateByPrimaryKeySelective(wallet, 
                		Column.balanceAmt,
                		Column.updateUser,
                		Column.updateTime);
                	//钱包明细
                	walletDetailManager.create(wallet.getWalletId(), 
                		SalesUserWalletDetailType.OUT_ACCOUNT.real(),
                		order.getCommission(),
                		SalesUserWalletDetailSource.SALES.real(),
                		order.getOrderId(),
                		null, 
                		updateUser);
            	}
    		}
    	}
    }
    
    public SalesUserWallet get(Integer walletId) {
    	return dao.selectByPrimaryKeyWithLogicalDelete(walletId, SalesUserWallet.NOT_DELETED);
    }
    
    public SalesUserWallet getByUserIdAndStoreId(Integer userId, Integer storeId) {
    	SalesUserWalletExample example = new SalesUserWalletExample();
    	example.createCriteria().andUserIdEqualTo(userId)
    	.andStoreIdEqualTo(storeId)
    	.andDeletedEqualTo(SalesUserWallet.NOT_DELETED);
    	return dao.selectOneByExample(example);
    }
    
    /**
     * 检查余额是否大于提现金额
     * @param walletId
     * @param applyAmt
     * @return
     */
    public Boolean checkBalance(Integer walletId, BigDecimal applyAmt) {
    	SalesUserWallet wallet = get(walletId);
    	return Check.isGreatThanEqual(wallet.getBalanceAmt(), applyAmt);
    }
}